﻿package src.entity {
	
	/**
	* 
	* Reliability project
	* -----------------------
	* @author  Dmitrij Boycov
	* @mail    dmitry.boycov@gmail.com
	* @date    April 27, 2010
	* @version 1
	* 
	*/
	
	import fl.data.DataProvider;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.MouseEvent;	
	import flash.geom.Point;
	import flash.ui.Mouse;
	import flash.utils.Timer;
	import flash.events.TimerEvent;
	import flash.filters.GlowFilter;
	import flash.filters.BitmapFilterQuality;
	import flash.text.TextField;	
	import flash.text.TextFormat;	
	import flash.text.TextFieldType;
	import flash.text.TextFieldAutoSize
	import flash.utils.Dictionary; 	
	import flash.display.GradientType;
	import flash.geom.Matrix;
	import flash.events.KeyboardEvent;	
	import flash.filters.BlurFilter;
	//		
	import gs.TweenLite;	
	// src
	import src.components.Confirm;
	import src.entity.Element;
	import src.util.Container;
	import src.common.OwnerEvent;	
	import src.components.BForm;
	import src.components.ElementForm;	
	import src.components.CalcForm;
	import src.util.Utils;
	import src.common.MsgEvent;
	import src.computation.LogicalProbabilisticMethod;
	import src.computation.Method;
	import src.components.ResForm;
	import src.components.HeaderBarButton;
	import src.components.StockForm;
	// astra
	import com.yahoo.astra.fl.managers.AlertManager;
	
	public class Scheme extends Sprite {
		
		private var sWidth:Number;
		private var sHeight:Number;
		private var basis:Sprite;
		private var navigation:Sprite;
		private var sColour = 0xFFFFAA;
		private var scale = 1;
		private var timer:Timer;
		private var currentDir:String;
		private var stageRef:Stage;
		private var ownerEvent:OwnerEvent;
		
		/**
		 * stock is - stockForm		 
		 */
		private var stock;
		// for header
		private var hHeight:Number = 25;
		private var hColour:int = 0x424242;// 0x939393;//0x737373;
		private var hColour2:int = 0x595959;//0x939393;
		private var glowColour = 0x3d4146;
		private var nameScheme:String = 'no name';
		private var descScheme:String = '';
		private var tf:TextField;
		//	containers
		private var elements:Container = new Container(); 
		private var nodes:Container = new Container(); 
		private var links:Container = new Container(); 
		//
		private var idBD:Number;
		private var cfRotation;
		
		/**
		* 	constructor
		* 	@param stageRef - stage of root
		*/ 			
		public function Scheme(stageRef:Stage) {	
			super();			
			this.stageRef = stageRef;		
			this.sWidth = stageRef.stageWidth;
			this.sHeight = stageRef.stageHeight;
			this.basis = this.createRectangle();
			this.basis.name = "BASIS";
			
			addChild(this.basis);
			this.navigation = this.createNavigation();
			this.navigation.x = this.sWidth -  this.navigation.width - 10;
			this.navigation.y = this.sHeight -  this.navigation.height - 10;
			addChild(this.navigation);	
			var header = this.createHeader();
			header.y = 0;
			header.x = this.sWidth - header.width;
			this.addChild(header);
			// create begin node and end node 
			var inNode = new Node();
			inNode.setName("in");
			inNode.x = this.stageRef.stageWidth / 2;
			inNode.y = header.height +10;
			inNode.addEventListener(Entity.ENTITY_ON_DOWN, onDownEntity);			
			this.basis.addChild(inNode);
			this.nodes.add(inNode);			
			var outNode = new Node();
			outNode.setName("out");
			outNode.x = this.stageRef.stageWidth / 2;
			outNode.y = this.stageRef.stageHeight - outNode.height - 10;
			outNode.addEventListener(Entity.ENTITY_ON_DOWN, onDownEntity);			
			this.basis.addChild(outNode);
			this.nodes.add(outNode);
			/////
			this.ownerEvent = OwnerEvent.getInstance();
			this.ownerEvent.addEventListener(OwnerEvent.NEED_RESET_OWNER_EVENT, onUpEntity);
			this.ownerEvent.addEventListener(OwnerEvent.NEED_DELETE_ENTITY, onDeleteEntity);
			// this is made to be able to listen keyboard
			this.stageRef.focus = this;			
			this.stageRef.addEventListener(KeyboardEvent.KEY_DOWN,this.ownerEvent.onKeyDown,true);
		}
		
		public function getIdBD() {
			return this.idBD;
		}
		
		public function setIdBD(id) {
			this.idBD = id;
		}
		
		/**
		 * setMask
		 * THis function set mask rectangle, reset active element
		 */
		public function setMask() {
			var maskRect = Utils.getMask(parent.width, parent.height);
			var blur = new BlurFilter();			
			blur.quality = BitmapFilterQuality.HIGH;
			blur.blurX = 8;
			blur.blurY = 8;
			this.filters = [blur];
			parent.addChild(maskRect);			
		}
		
		/**
		 * unmask
		 * This function remove mask rectangle and form window, set stage focus.		 
		 */
		public function unmask() {		
			try{
				this.filters = [];
				parent.removeChildAt(parent.numChildren - 1);
				parent.removeChildAt(parent.numChildren - 1);
				// this is made to be able to listen keyboard
				this.stageRef.stageFocusRect = false;// To remove the crappy yellow rect on all focused InteractiveObject
				this.stageRef.focus = this;
			}catch(errObject:Error) {
				trace(errObject.message);
			}
		}
		
		public function removeEntity() {
			var ent = this.ownerEvent.getActiveEntity();		
			if (ent is Element) {
				this.elements.remove(ent.getId());	
			}else if (ent is Node) {
				this.nodes.remove(ent.getId());	
			}else if (ent is Link) {
				ent.unlink();
				this.links.remove(ent.getId());	
			}
			this.basis.removeChild(ent);
			ent = null;
		}
		
		private function onDeleteEntity(event) {			
			var ent = this.ownerEvent.getActiveEntity();
			if (this.basis.contains(ent)) {
				this.setMask();
				var form = null;						
				form = new Confirm("Удалить этот элемент?");	
				form.x = parent.width / 2 - form.width/2;
				form.y = parent.height / 2 - form.height / 2;				
				var scheme = this;
				form.addEventListener(BForm.FORM_CLOSE, function(e:Event) {
					scheme.unmask();								
				});	
				form.addEventListener(BForm.FORM_OK, function(e:Event) {					
					scheme.removeEntity();
					scheme.unmask();
				});
				parent.addChild(form);		
			}
		}		
		
		/**
		 * getDropEntity
		 * This function define entity, that under points.
		 * @param	points
		 */
		public function getDropEntity(points:Array) {
			if(points!=null){
				for (var i = 0; i < points.length;i++ ) {
					var ar:Array = stageRef.getObjectsUnderPoint(points[i]);
					for (var j = 0; j < ar.length;j++ ){
						if (ar[j] is IObjectOfScheme) {						
							return ar[j];
						} 
					}				
				}				
			}
			return null;
		}		
		
		//  
		private function createRectangle() {
			var rect:Sprite = new Sprite();			
			var ellipseSize:int = 0;
			rect.graphics.lineStyle(0.2);
			rect.graphics.beginFill(sColour);
			rect.graphics.drawRoundRect(0, 0, sWidth, sHeight, ellipseSize, ellipseSize);
			rect.graphics.endFill();
			rect.width = sWidth;
			rect.height = sHeight;
			rect.name = "BASIS";
			return rect;
		}
		
		private function createTF(text) {
			var FORMAT:TextFormat = new TextFormat();
			FORMAT.font = "Georgia";			
			FORMAT.align = "left";
			FORMAT.bold = true;
			//FORMAT.color = 0x154672;
			FORMAT.color = 0xffffff;
			FORMAT.size = 14;
			
			var tf = new TextField();			
			tf.autoSize = TextFieldAutoSize.LEFT;

			tf.defaultTextFormat = FORMAT;
			tf.type = TextFieldType.DYNAMIC;
			tf.text = text;			
			tf.height = 20;			
			tf.border = false;
			tf.background = false;			
			tf.sharpness = 4;			
			tf.selectable = false;			
			return tf; 
		}
		
		private function changeHeader(event:MouseEvent) {			
			this.setMask();
			var form = new BForm("Схема");
			var dict:Dictionary = new Dictionary();
			dict["name"] = this.nameScheme
			dict["description"] = this.descScheme;
			form.setData(dict);
			form.x = parent.width / 2 - form.width/2;
			form.y = parent.height / 2 - form.height / 2;
			var scheme = this;
			form.addEventListener(BForm.FORM_CLOSE, function(e:Event) {				
				scheme.unmask();				
			});
			form.addEventListener(BForm.FORM_OK, function(e:Event) {
				var dict:Dictionary = form.getData();
				nameScheme  = dict["name"];
				tf.text = dict["name"] as String;
				descScheme = dict["description"];				
				scheme.unmask();				
			});
			parent.addChild(form);
		}
		
		private function createHeader() {			
			var dist:Number = 5;		
			var centerPart:Sprite = new Sprite();
			// close button			
			var closeButton = new HeaderBarButton(new IcoClose(), 'Закрыть');	
			closeButton.x = this.basis.width - closeButton.width -dist;
			closeButton.y = (hHeight - closeButton.height) / 2;
			closeButton.addEventListener(MouseEvent.CLICK, close);
			// save Button
			var saveButton = new HeaderBarButton(new IcoSave(), 'Сохранить');
			saveButton.x =  closeButton.x - saveButton.width - dist;
			saveButton.y = (hHeight - saveButton.height) / 2;
			saveButton.addEventListener(MouseEvent.CLICK, save);
			// calc button
			var calcButton = new HeaderBarButton(new IcoCalc(), 'Вычислить');		
			calcButton.x =  saveButton.x - calcButton.width - dist;
			calcButton.y = (hHeight - calcButton.height)/2;
			calcButton.addEventListener(MouseEvent.CLICK, showCalcForm);
			// stock button
			var stockButton = new HeaderBarButton(new IcoStock(), 'Склад');
			stockButton.x =  calcButton.x - stockButton.width - dist;
			stockButton.y = (hHeight - stockButton.height)/2;
			stockButton.addEventListener(MouseEvent.CLICK, showStockForm);
			
			tf = this.createTF(this.nameScheme);
			tf.doubleClickEnabled = true;
			tf.addEventListener(MouseEvent.DOUBLE_CLICK, changeHeader);			
			var rotateMatrix:Matrix = new Matrix();
			rotateMatrix.createGradientBox(this.basis.width, hHeight, -Math.PI / 2, 0, 0);			
			centerPart.graphics.beginGradientFill(GradientType.LINEAR,[hColour,hColour2], [1, 1],[ 0, 255],rotateMatrix);
			centerPart.graphics.drawRect(0, 0, this.basis.width, hHeight);
			centerPart.graphics.endFill();
			centerPart.filters = [Utils.getDropShadowFilter(glowColour)];			
			tf.x = hHeight/2;
			tf.y = 0;
			centerPart.addChild(tf);			
			//			
			var actualPrompt:Sprite = new Sprite();
			actualPrompt.addChild(centerPart);			
			actualPrompt.addChild(closeButton);			
			actualPrompt.addChild(saveButton);
			actualPrompt.addChild(calcButton);
			actualPrompt.addChild(stockButton);
			return actualPrompt;
		}
		
		private function showStockForm(event) {
			this.setMask();
			if (this.stock == null) {
				this.stock = new StockForm();
				this.stock.addEventListener(BForm.FORM_CLOSE, function(e:Event) {				
				scheme.unmask();				
			});	
			}		
			this.stock.x = parent.width / 2 - this.stock.width/2;
			this.stock.y = parent.height / 2 - this.stock.height / 2;			
			var scheme = this;		
			parent.addChild(this.stock);
		}
		
		private function save(event) {
			this.setMask();
			var form = null;
			form = new Confirm("Сохранить схему?");
			form.x = parent.width / 2 - form.width/2;
			form.y = parent.height / 2 - form.height / 2;
			var scheme = this;
			form.addEventListener(BForm.FORM_CLOSE, function(e:Event) {
				scheme.unmask();								
			});	
			form.addEventListener(BForm.FORM_OK, function(e:Event) {				
				var str = "<scheme>";
				if(this.idBD != null){
					str += "<id>" + this.idBD + "</id>";
				}
				str += scheme.links.toXML("links");
				str += scheme.elements.toXML("elements");
				str += scheme.nodes.toXML("nodes");
				str += "</scheme>";
				trace(str);
				scheme.unmask();
			});
			parent.addChild(form);
		}
		
		private function close(event) {			
			this.setMask();
			var form = null;						
			form = new Confirm("Закрыть схему?");	
			form.x = parent.width / 2 - form.width/2;
			form.y = parent.height / 2 - form.height / 2;				
			var scheme = this;
			form.addEventListener(BForm.FORM_CLOSE, function(e:Event) {
				scheme.unmask();								
			});	
			form.addEventListener(BForm.FORM_OK, function(e:Event) {				
				scheme.unmask();
				parent.removeChild(scheme);
				scheme = null;
			});
			parent.addChild(form);
		}
		
		/**
		 * showCalcForm
		 * It show calc form. And it start computation.
		 * @param	event
		 */
		private function showCalcForm(event:MouseEvent) {
			this.setMask();
			var form = null;						
			form = new CalcForm();	
			form.x = parent.width / 2 - form.width/2;
			form.y = parent.height / 2 - form.height / 2;
			var scheme = this;
			form.addEventListener(BForm.FORM_CLOSE, function(e:Event) {				
				scheme.unmask();			
			});			
			form.addEventListener(BForm.FORM_OK,function(e:Event) {
				var dict:Dictionary = form.getData();	
				var method = dict["method"];			
				if(method!=null){
					method.addEventListener(Method.ERROR, function(event:MsgEvent) {
						AlertManager.createAlert(parent, event.msg, "Ошибка");
						method = null;
					});					
					//									
					method.addEventListener(Method.STOP_COMPUTATION, function(event:Event) {							
						var res = method.getResult();	
						scheme.unmask();
						scheme.setMask();
						var form2 = null;						
						form2 = new ResForm();
						var dict2 = new Dictionary();
						dict2["result"] = res;			
						form2.setData(dict2);
						form2.x = parent.width / 2 - form.width/2;
						form2.y = parent.height / 2 - form.height / 2;
						form2.addEventListener(BForm.FORM_OK, function(e:Event) {
							scheme.unmask();
						});
						var dopForm = method.getResForm();
						if (dopForm != null) {
							form2.add(dopForm);
						}
						parent.addChild(form2);						
						method = null;
					});					
					method.setTime(new Number(dict["time"]));					
					if(scheme.stock!=null){
						var stDict = scheme.stock.getData();						
						if(stDict!=null && stDict["data"]!=null){
							method.setStock(stDict["data"].clone());
						}
					}
					method.setContainers(scheme.elements.containerToDict(), 
											scheme.nodes.containerToDict(), 
											scheme.links.containerToDict());
					method.startComputation();
					
				}
			});
			parent.addChild(form);
		}		
		
	/*	private function cleareScheme() {
			this.cleareContainer(this.elements);
			this.cleareContainer(this.links);
			this.cleareContainer(this.nodes);
		}
		
		private function cleareContainer(container) {
			container.first();
			var a = container.getNext();
			while (a != null) {
				container.remove(a.getId());
				this.basis.removeChild(a);
				a = container.getNext();
			}			
		}
		
		private function refresh() {
			this.elements.first();
			var a = this.elements.getNext();
			while (a != null) {
				this.basis.addChild(a);
				a = this.elements.getNext();
			}
			this.nodes.first();
			a = this.nodes.getNext();
			while (a != null) {
				this.basis.addChild(a);
				a = this.nodes.getNext();
			}
		}
	*/	
		/**
		 *  createNavigation
		 * 	Create navigation panel, which allows zoom in,zoom out, move up,
		 * 	move down, move left and move right.
		*/ 
		private function createNavigation() {			
			// init
			var border:Number = 3;
			var nColour = 0xDDDDDD;
			var nAlpha = 0.5;
			var nav = new Sprite();			
			var zoomin = new ZoomIn();										// +	
			zoomin.addEventListener(MouseEvent.MOUSE_DOWN, this.zoomIn);
			this.addListenersToButton(zoomin);
			var zoomout = new ZoomOut();									// -
			zoomout.addEventListener(MouseEvent.MOUSE_DOWN, this.zoomOut);
			this.addListenersToButton(zoomout);
			var dirUp = new Course();  										// up
			dirUp.addEventListener(MouseEvent.MOUSE_DOWN, moveUp);
			this.addListenersToButton(dirUp);
			var dirDown = new Course();										// down
			dirDown.addEventListener(MouseEvent.MOUSE_DOWN, moveDown);
			this.addListenersToButton(dirDown);
			var dirLeft = new Course();										// left
			dirLeft.addEventListener(MouseEvent.MOUSE_DOWN, moveLeft);			
			this.addListenersToButton(dirLeft);
			var dirRight = new Course();									// right
			dirRight.addEventListener(MouseEvent.MOUSE_DOWN, moveRight);
			this.addListenersToButton(dirRight);
			var nWidth = 2 * (dirUp.height + border) + zoomin.width + 2 * border;
			var nHeight = 2 * (dirUp.height + border) + 2 * zoomin.height + 3 * border;
			// draw basis
			var ellipseSize:int = 4*border;
			//nav.graphics.lineStyle(0);
			nav.graphics.beginFill(nColour);
			nav.graphics.drawRoundRect(0, 0, nWidth, nHeight, ellipseSize, ellipseSize);
			nav.alpha = nAlpha;
			nav.graphics.endFill();
			// add buttons
			dirUp.x = dirUp.height + 2 * border;
			dirUp.y = border;
			nav.addChild(dirUp);
			//--
			dirLeft.rotation = -90;
			dirLeft.x = border;
			dirLeft.y = dirUp.y +  dirUp.height + border + dirLeft.height;
			nav.addChild(dirLeft);
			//--
			zoomin.x = dirUp.x
			zoomin.y = dirUp.y + dirUp.height + border;
			nav.addChild(zoomin);
			//--
			zoomout.x = dirUp.x;
			zoomout.y = zoomin.y+zoomin.height+border;
			nav.addChild(zoomout);
			//--
			dirDown.rotation = 180;
			dirDown.x = dirUp.x + dirDown.width;
			dirDown.y = zoomout.y+ zoomout.height+ border + dirDown.height;
			nav.addChild(dirDown);
			//--
			dirRight.rotation = 90;
			dirRight.y = zoomin.y;
			dirRight.x = zoomin.x + zoomin.width + border + dirRight.width;
			nav.addChild(dirRight);
			
			nav.addEventListener(MouseEvent.MOUSE_DOWN, doStartDrag);
			nav.addEventListener(MouseEvent.MOUSE_UP, doStopDrag);			
			nav.buttonMode = true;			
			nav.useHandCursor = true;
			return nav;
		}
		
		/**
		* 	actions for button of navigation panel
		*//////////////////////////////////////////////////////////////////////// 
		private function endMoveNav(event:MouseEvent) {
			event.target.removeEventListener(MouseEvent.MOUSE_UP, endMoveNav);
			this.timer.removeEventListener(TimerEvent.TIMER, moveNav);
			this.timer.stop();
			this.timer = null;
			this.currentDir = null;
		}
		
		private function startMoveNav(event:MouseEvent){
			event.target.addEventListener(MouseEvent.MOUSE_UP, endMoveNav);
			this.timer = new Timer(50,0);
			this.timer.addEventListener(TimerEvent.TIMER, moveNav);
			this.timer.start();
		}
		
		private function moveNav(event:TimerEvent) {			
			if (this.currentDir != null) {
				var obj = new Object();							//
				var x1 = this.basis.x;							//	+-------------+b
				var y1 = this.basis.y + this.basis.height;		//	|			  |
				var a:Point = new Point(x1, y1);				//	|			  |
				a = parent.localToGlobal(a);					//	|			  |	
				var x2 = this.basis.x + this.basis.width;		//	|			  |	
				var y2 = this.basis.y; 							//	|			  |	
				var b:Point = new Point(x2, y2);				// a+-------------+
				b = parent.localToGlobal(b);					//
				switch(this.currentDir) {					
					case "Right":
						if ((a.x < 0) || (b.x < this.stageRef.stageWidth)) {
							obj.x = this.basis.x + 10;
						}
					break;	
					case "Left"	:
						if ((a.x >= 0) || (b.x > this.stageRef.stageWidth)) {
							obj.x = this.basis.x - 10;
						}
					break;	
					case "Up":
						if((b.y >= 0) || (a.y > this.stageRef.stageHeight)){						
							obj.y = this.basis.y - 10;				
						}	
					break;
					case "Down"	:
						if((b.y < 0) || (a.y < this.stageRef.stageHeight)){
							obj.y = this.basis.y + 10;
						}
					break;
				}
				TweenLite.to(this.basis, 1, obj);				
			}			
		}
		
		private function zoomIn(event:MouseEvent):void {
			this.scale += 1;
			TweenLite.to(this.basis, 1, {scaleX:this.scale, scaleY:this.scale});
		}
		
		private function zoomOut(event:MouseEvent):void {
			if(this.scale>1){
				this.scale -= 1;
				TweenLite.to(this.basis, 1, { scaleX:this.scale, scaleY:this.scale } );
			}	
		}
		
		private function moveLeft(event:MouseEvent) {			
			this.currentDir = "Left";
			this.startMoveNav(event);
		}
		
		private function moveRight(event:MouseEvent) {
			this.currentDir = "Right";
			this.startMoveNav(event);			
		}
		
		private function moveUp(event:MouseEvent) {			
			this.currentDir = "Up";
			this.startMoveNav(event);				
		}
		
		private function moveDown(event:MouseEvent) {			
			this.currentDir = "Down";
			this.startMoveNav(event);
		}				
		//////////////////////////////////////////////////////////////////////////
		
		/**
		* 	Event of Mouse for Button
		*///////////////////////////////////////////////////////////////////////// 
		private function addListenersToButton(button) {
			button.gotoAndStop(1)
			button.addEventListener(MouseEvent.MOUSE_OVER, onOverButton);
			button.addEventListener(MouseEvent.MOUSE_OUT, onOutButton);
			button.addEventListener(MouseEvent.MOUSE_UP, onUpButton);
			button.addEventListener(MouseEvent.MOUSE_DOWN, onDownButton);
		}
		
		private function onOverButton(e:MouseEvent) {			
			e.target.gotoAndStop(2);
		}
		private function onOutButton(e:MouseEvent) {
			e.target.gotoAndStop(1);
		}
		private function onUpButton(e:MouseEvent) {
			e.target.gotoAndStop(2);
		}
		private function onDownButton(e:MouseEvent) {
			e.target.gotoAndStop(3);
		}		
		////////////////////////////////////////////////////////////////////////////		
		
		/*
		* 	Drag and drop for navigation panel
		*////////////////////////////////////////////////////////////////////////////
		private function doStartDrag(event:MouseEvent):void {			
			if (this.ownerEvent.getOwnerEvent() == null) {
				this.ownerEvent.setOwnerEvent(this.navigation);
				this.navigation.startDrag();
			}
		}		
		private function doStopDrag(event:MouseEvent):void {			
			if(this.ownerEvent.getOwnerEvent() == this.navigation){				
				this.navigation.stopDrag();	
				this.ownerEvent.resetOwnerEvent();
			} 
		}
		////////////////////////////////////////////////////////////////////////////////		
		
		/**
		 * Handlers for control activity of entity
		 * @param	e
		 */		
		private function onDownEntity(e:Event) {			
			if (this.ownerEvent.getOwnerEvent() == null) {				
				this.ownerEvent.setOwnerEvent(e.target);
				this.basis.setChildIndex(e.target as Sprite, (this.basis.numChildren - 1));
				e.target.doActionOnDown();
			}
		}
		
		private function onUpEntity(e:Event) {			
			if (this.ownerEvent.getOwnerEvent() != null) {
				this.ownerEvent.getOwnerEvent()
				if(this.ownerEvent.getOwnerEvent() is IEntity){
					this.ownerEvent.getOwnerEvent().doActionOnUp();
				}	
				this.ownerEvent.resetOwnerEvent();
			}
		}
		
		private function onDoubleClickEntity(e:Event) {			
			if(e.target is IEntity){				
				this.setMask();
				var form = null;
				var ent = e.target;
				var scheme = this;
				var dict:Dictionary = new Dictionary();
				if(ent.getType() == Node.TYPE){
					form = new BForm("Узел");					
					dict["name"] = ent.getName();
					dict["description"] = ent.getDescription();
					form.setData(dict);
				}
				if(ent.getType() == Link.TYPE){
					form = new BForm("Связь");					
					dict["name"] = ent.getName();
					dict["description"] = ent.getDescription();
					form.setData(dict);
				}
				if(ent.getType() == Element.TYPE){									
					form = new ElementForm("Элемент");
					dict["name"] = ent.getName();
					dict["description"] = ent.getDescription();
					dict["law"] = ent.getLaw();
					dict["recovery"] = ent.getRecovery();
					dict["stockId"] = ent.getStockId();					
					if(this.stock!=null){
						var d = this.stock.getData();
						if(d["data"])
							dict["stock"] = d["data"];
					}
					form.setData(dict);
				}
				form.x = parent.width / 2 - form.width/2;
				form.y = parent.height / 2 - form.height / 2;
				form.addEventListener(BForm.FORM_CLOSE, function(e:Event) {				
					scheme.unmask();
				});
				if(e.target.getType() == Link.TYPE || e.target.getType() == Node.TYPE){
					form.addEventListener(BForm.FORM_OK, function(e:Event) {
						var dict:Dictionary = form.getData();
						ent.setName(dict["name"]);
						ent.setDescription(dict["description"]);						
						scheme.unmask();
					});
				}
				if(e.target.getType() == Element.TYPE){
					form.addEventListener(BForm.FORM_OK, function(e:Event) {						
						var dict:Dictionary = form.getData();
						ent.setName(dict["name"]);
						ent.setDescription(dict["description"]);						
						ent.setLaw(dict["law"]);
						ent.setRecovery(dict["recovery"]);
						ent.setStockId(dict["stockId"]);
						scheme.unmask();
					});
				}
				parent.addChild(form);	
			}			
		}
	
		private function changeCursorOnRotation(e:Event) {
			if (this.ownerEvent.getOwnerEvent() == null) {
				var m:Point = new Point(mouseX, mouseY)					
				m = localToGlobal(m);
				if (!this.cfRotation) {
					e.target.rotatedNow = 1; // init
					var el = e.target as Element;
					var point = new Point(el.x+el.width/2, el.y+el.height/2);
					point = localToGlobal(point);					
					Mouse.hide();
					this.cfRotation = new CursorForRotation();					
					this.cfRotation.mouseEnabled = false;
					this.cfRotation.mouseChildren = false;
					this.cfRotation.gotoAndStop(1);
					this.cfRotation.x = m.x;
					this.cfRotation.y = m.y;					
					parent.addChild(this.cfRotation);					
					this.cfRotation.startDrag();
				}
				m = null;
			}			
		}
		
		private function resetCursor(e:Event) {
			if (this.ownerEvent.getOwnerEvent() == null || this.ownerEvent.getOwnerEvent() == e.target) {
				if(this.cfRotation != null){
					parent.removeChild(this.cfRotation);
				}
				this.cfRotation = null;
				Mouse.show();
			}
		}
		
		/**
		 * removeListeners
		 * Delete listeners, 
		 */
		private function removeListeners() {
			this.removeEventListener(MouseEvent.MOUSE_DOWN, onAddElement);
			this.removeEventListener(MouseEvent.MOUSE_DOWN, onAddNode);	
			this.removeEventListener(MouseEvent.MOUSE_DOWN, onAddLink);
		}
		 
		/**
		 * onAddElement
		 * handlers for create new entity
		 * @param	event
		 */
		private function onAddElement(event:MouseEvent) {
			this.removeListeners();			
			var el = new Element();
			el.addEventListener(Entity.ENTITY_ON_DOWN, onDownEntity);			
			el.addEventListener(Element.CHANGE_CURSOR_ON_ROTATION, changeCursorOnRotation);
			el.addEventListener(Element.RESET_CURSOR, resetCursor);
			el.addEventListener(Entity.DOUBLE_CLICK_ON_ELEMENT, onDoubleClickEntity);
			el.x = mouseX;
			el.y = mouseY;			
			this.basis.addChild(el);
			this.elements.add(el);
		}
		
		/**
		 * onAddNode
		 * handlers for create new node
		 * @param	event
		 */
		private function onAddNode(event:MouseEvent) {
			this.removeListeners();
			var node = new Node();
			node.x = mouseX;
			node.y = mouseY;
			node.addEventListener(Entity.ENTITY_ON_DOWN, onDownEntity);	
			node.addEventListener(Entity.DOUBLE_CLICK_ON_ELEMENT, onDoubleClickEntity);
			this.basis.addChild(node);
			this.nodes.add(node);
		}
		
		/**
		 * onAddLink
		 * handlers for create new link
		 * @param	event
		 */
		private function onAddLink(event:MouseEvent) {
			this.removeListeners();
			var link = new Link();
			link.setParent(this);
			link.x = mouseX;
			link.y = mouseY;
			link.addEventListener(Entity.ENTITY_ON_DOWN, onDownEntity);
			link.addEventListener(Entity.DOUBLE_CLICK_ON_ELEMENT, onDoubleClickEntity);
			this.basis.addChild(link);
			link.startDraw(event);			
			this.links.add(link);			
		}
		 
		/**
		 * This functions add listeners for mouse doun event.
		 */
		public function addElement() {
			this.removeListeners();
			this.addEventListener(MouseEvent.MOUSE_DOWN, onAddElement);
		}		
		
		public function addNode() {
			this.removeListeners();
			this.addEventListener(MouseEvent.MOUSE_DOWN, onAddNode);			
		}
		
		public function addLink() {
			this.removeListeners();
			this.addEventListener(MouseEvent.MOUSE_DOWN, onAddLink);			
		}
		////////
	}
}